<!DOCTYPE html><html lang="cn" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><title>NoSQL篇-Redis数据库 | 碧蓝幻想</title><meta name="author" content="阿尔托莉雅"><meta name="copyright" content="阿尔托莉雅"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="1.NoSQL的概念： NoSQL（Not Only SQL）即不仅仅是SQL，泛指非关系型的数据库，它可以作为关系型数据库的良好补充。随着互联网web2.0网站的兴起，非关系型的数据库现在成了一个极其热门的新领域，非关系数据库产品的发展非常迅速。  为什么会出现NoSQL技术：传统的关系型数据库在应付web2.0网站暴露了很多难以克服的问题：  数据的高并发读写 海量数据的高效率存储和访问 数据">
<meta property="og:type" content="article">
<meta property="og:title" content="NoSQL篇-Redis数据库">
<meta property="og:url" content="http://example.com/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/B2.NoSQL%E6%95%B0%E6%8D%AE%E5%BA%93%20-%20Redis/index.html">
<meta property="og:site_name" content="碧蓝幻想">
<meta property="og:description" content="1.NoSQL的概念： NoSQL（Not Only SQL）即不仅仅是SQL，泛指非关系型的数据库，它可以作为关系型数据库的良好补充。随着互联网web2.0网站的兴起，非关系型的数据库现在成了一个极其热门的新领域，非关系数据库产品的发展非常迅速。  为什么会出现NoSQL技术：传统的关系型数据库在应付web2.0网站暴露了很多难以克服的问题：  数据的高并发读写 海量数据的高效率存储和访问 数据">
<meta property="og:locale">
<meta property="og:image" content="http://example.com/images/Otherwallpaper/avatar.png">
<meta property="article:published_time" content="2023-03-13T12:32:38.441Z">
<meta property="article:modified_time" content="2023-03-13T12:42:21.155Z">
<meta property="article:author" content="阿尔托莉雅">
<meta property="article:tag" content="Redis NoSQL 数据库">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://example.com/images/Otherwallpaper/avatar.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/B2.NoSQL%E6%95%B0%E6%8D%AE%E5%BA%93%20-%20Redis/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: 'Copy successfully',
    error: 'Copy error',
    noSupport: 'The browser does not support'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: 'Just',
    min: 'minutes ago',
    hour: 'hours ago',
    day: 'days ago',
    month: 'months ago'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isAnchor: false,
  percent: {
    toc: true,
    rightside: false,
  }
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'NoSQL篇-Redis数据库',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2023-03-13 20:42:21'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
    win.getCSS = (url,id = false) => new Promise((resolve, reject) => {
      const link = document.createElement('link')
      link.rel = 'stylesheet'
      link.href = url
      if (id) link.id = id
      link.onerror = reject
      link.onload = link.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        link.onload = link.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(link)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/images/Otherwallpaper/avatar.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">Articles</div><div class="length-num">11</div></a><a href="/tags/"><div class="headline">Tags</div><div class="length-num">4</div></a><a href="/categories/"><div class="headline">Categories</div><div class="length-num">2</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/archive/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 工具</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/images/"><i class="fa-fw fas fa-image"></i><span> 图库</span></a></li><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/video/"><i class="fa-fw fas fa-video"></i><span> 视频</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 链接</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('/images/PCwallpaper/backgroud2.jpg')"><nav id="nav"><span id="blog-info"><a href="/" title="碧蓝幻想"><span class="site-name">碧蓝幻想</span></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/archive/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 工具</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/images/"><i class="fa-fw fas fa-image"></i><span> 图库</span></a></li><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/video/"><i class="fa-fw fas fa-video"></i><span> 视频</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 链接</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">NoSQL篇-Redis数据库</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">Created</span><time class="post-meta-date-created" datetime="2023-03-13T12:32:38.441Z" title="Created 2023-03-13 20:32:38">2023-03-13</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2023-03-13T12:42:21.155Z" title="Updated 2023-03-13 20:42:21">2023-03-13</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="NoSQL篇-Redis数据库"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">Post View:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="1-NoSQL的概念："><a href="#1-NoSQL的概念：" class="headerlink" title="1.NoSQL的概念："></a>1.NoSQL的概念：</h2><ul>
<li><p>NoSQL（Not Only SQL）即不仅仅是SQL，泛指非关系型的数据库，它可以作为关系型数据库的良好补充。随着互联网web2.0网站的兴起，非关系型的数据库现在成了一个极其热门的新领域，非关系数据库产品的发展非常迅速。</p>
</li>
<li><p>为什么会出现NoSQL技术：传统的关系型数据库在应付web2.0网站暴露了很多难以克服的问题：</p>
<ul>
<li>数据的高并发读写</li>
<li>海量数据的高效率存储和访问</li>
<li>数据库的高扩展和高可用</li>
</ul>
</li>
<li><p>NoSQL的类别：</p>
<ul>
<li>键值（Key-Value）存储数据库：这一类数据库主要会使用到一个哈希表<ul>
<li>应用：内容缓存，主要用于处理大量数据的高访问负载。</li>
<li>优势：快速查询</li>
<li>劣势：存储的数据缺少结构化</li>
</ul>
</li>
<li>列存储数据库：这部分数据库通常是用来应对分布式存储的海量数据<ul>
<li>应用：分布式文件系统</li>
<li>优势：查找速度快，可扩展性强，更容易进行分布式扩展</li>
<li>劣势：功能相对局限</li>
</ul>
</li>
<li>文档型数据库：该类型的数据模型是版本化的文档，半结构化的文档以特定的格式存储<ul>
<li>应用：Web应用</li>
<li>优势：数据结构要求不严格</li>
<li>劣势：查询性能不高，且缺乏统一的查询语法</li>
</ul>
</li>
<li>图形（Graph）数据库：图形结构的数据库同其他行列以及刚性结构的SQL数据库不同，它是使用灵活的图形模型，并且能够扩展到多个服务器上<ul>
<li>应用：社交网络</li>
<li>优势：利用图结构相关算法</li>
<li>劣势：需要对整个图做计算才能得出结果，不容易做分布式的集群方案</li>
</ul>
</li>
</ul>
</li>
<li><p>NoSQL适应场景：</p>
<ul>
<li>数据模型比较简单</li>
<li>需要灵活性更强的IT系统</li>
<li>对数据库性能要求较高</li>
<li>不需要高度的数据一致性</li>
<li>对于给定key，比较容易映射复杂的环境</li>
<li>取最新的N个数据（如排行榜）</li>
<li>数据缓存</li>
</ul>
</li>
<li><p>CAP：</p>
<ul>
<li>Consistency（强一致性）</li>
<li>Availability（可用性）</li>
<li>Partition tolerance（分区容错性）</li>
</ul>
</li>
<li><p>什么是BASE：</p>
<ul>
<li>BASE就是为了解决关系数据库强一致性引起的问题而导致可用性降低而提出的解决方案。BASE其实是下面三个术语的缩写：<ul>
<li>基本可用（&#x3D;&#x3D;B&#x3D;&#x3D;asically &#x3D;&#x3D;A&#x3D;&#x3D;vailable）</li>
<li>软状态（&#x3D;&#x3D;S&#x3D;&#x3D;oft state）</li>
<li>最终一致（&#x3D;&#x3D;E&#x3D;&#x3D;ventually consistent）</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="2-Redis概念："><a href="#2-Redis概念：" class="headerlink" title="2.Redis概念："></a>2.Redis概念：</h2><ul>
<li><p>Redis诞生于2009年全称是Remote Dictionary Server，远程词典服务器</p>
</li>
<li><p>redis是一款高性能的NOSQL的系列的基于内存的键值型的非关系型数据库，<strong>redis是单线程的</strong></p>
</li>
<li><p>特征：</p>
<ul>
<li>键值（key-value）型，value支持多种不同数据结构，功能丰富</li>
<li>单线程，每个命令具备原子性</li>
<li>低延迟，速度快（基于内存、IO多路复用、良好的编码）</li>
<li>支持数据持久化</li>
<li>支持主从集群、分片集群</li>
<li>支持多语言客户端</li>
</ul>
</li>
<li><p>关系型数据库与非关系型数据库：</p>
<table>
<thead>
<tr>
<th></th>
<th>关系型数据库</th>
<th>非关系型数据库</th>
</tr>
</thead>
<tbody><tr>
<td>数据结构</td>
<td>结构化（表和表的约束）</td>
<td>非结构化（键值类型Redis，文档类型MongoDB，列类型HBase，Graph类型Neo4j）</td>
</tr>
<tr>
<td>数据关联</td>
<td>关联的（表的外键）</td>
<td>无关联的</td>
</tr>
<tr>
<td>查询方式</td>
<td>SQL查询</td>
<td>非SQL查询</td>
</tr>
<tr>
<td>事务特性</td>
<td>ACID（事务的四大特征）</td>
<td>BASE</td>
</tr>
<tr>
<td>存储方式</td>
<td>磁盘</td>
<td>大多存储在内存</td>
</tr>
<tr>
<td>扩展性</td>
<td>垂直</td>
<td>水平</td>
</tr>
</tbody></table>
<ul>
<li>使用场景：<ul>
<li>SQL数据库：1) 数据结构固定，2) 相关业务对数据安全性一致性要求较高</li>
<li>NOSQL数据库：1) 数据结构不固定，2) 对一致性，安全性要求不高，3) 对性能要求较高</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="3-下载安装："><a href="#3-下载安装：" class="headerlink" title="3.下载安装："></a>3.下载安装：</h2><ul>
<li><p>yum安装：</p>
<ul>
<li><p>安装：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y redis</span><br></pre></td></tr></table></figure>
</li>
<li><p>重启服务：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl restart redis</span><br></pre></td></tr></table></figure>
</li>
<li><p>redis的配置文件：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/redis.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改内容如下</span></span><br><span class="line"></span><br><span class="line">[Unit]</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">服务描述</span></span><br><span class="line">Description=Redis Server Manager</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">服务类别</span></span><br><span class="line">After=network.target</span><br><span class="line">[Service]</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">后台运行的形式</span></span><br><span class="line">Type=forking</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">服务命令</span></span><br><span class="line">ExecStart=/usr/local/redis-6.2.7/bin/redis-server /etc/redis.conf</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">给服务分配独立的临时空间</span></span><br><span class="line">PrivateTmp=true</span><br><span class="line">[Install]</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">运行级别下服务安装的相关设置，可设置为多用户，即系统运行级别为3</span></span><br><span class="line">WantedBy=multi-user.target</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用redis客户端进行连接：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -p 6379 -a 123456</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>docker安装：</p>
<ul>
<li><p>上传redis.conf配置文件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://blog.csdn.net/qq_56776641/article/details/129057235?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129057235%22%2C%22source%22%3A%22qq_56776641%22%7D</span><br></pre></td></tr></table></figure>
</li>
<li><p>修改配置文件中的密码：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">vim ~/redis/redis.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">内容</span></span><br><span class="line">requirepass 123456</span><br></pre></td></tr></table></figure>
</li>
<li><p>创建容器，设置端口映射</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">docker run -id --name=c_redis -p 6379:6379 \</span><br><span class="line">-v $PWD/data:/data -v $PWD/redis.conf:/etc/redis/redis.conf \</span><br><span class="line">redis:6.2.4</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--restart=always：总是开机启动</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--appendonly <span class="built_in">yes</span>：开启redis 持久化</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">–requirepass：设置密码</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>进入redis容器</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker exec -it c_redis /bin/bash</span><br></pre></td></tr></table></figure>
</li>
<li><p>启动redis客户端：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -p 6379 -a 123456</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<h2 id="4-redis的数据结构："><a href="#4-redis的数据结构：" class="headerlink" title="4.redis的数据结构："></a>4.redis的数据结构：</h2><ul>
<li><p>redis存储的是：key，value格式的数据，其中key都是字符串，value常用的有8种不同的数据结构</p>
</li>
<li><p>value的数据结构：</p>
<table>
<thead>
<tr>
<th>基本数据结构</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>字符串类型 String</td>
<td>String</td>
</tr>
<tr>
<td>哈希类型 Hash</td>
<td>map格式</td>
</tr>
<tr>
<td>列表类型 List</td>
<td>linkedlist格式。支持重复元素</td>
</tr>
<tr>
<td>集合类型 Set</td>
<td>不允许重复元素</td>
</tr>
<tr>
<td>有序集合类型 SortedSet</td>
<td>不允许重复元素，且元素有顺序</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>特殊数据结构</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>Geo</td>
<td>存储的地理位置的经纬度</td>
</tr>
<tr>
<td>BitMap</td>
<td>本身不是一种数据类型， 实际上它就是字符串，可以实现对位的操作</td>
</tr>
<tr>
<td>HyperLog</td>
<td>Redis HyperLogLog 是用来做基数统计的算法</td>
</tr>
</tbody></table>
</li>
</ul>
<h2 id="5-命令操作："><a href="#5-命令操作：" class="headerlink" title="5.命令操作："></a>5.命令操作：</h2><h3 id="2-通用命令："><a href="#2-通用命令：" class="headerlink" title="2.通用命令："></a>2.通用命令：</h3><table>
<thead>
<tr>
<th>格式</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>select [数据库号]</td>
<td>切换数据库（redis的数据库有16个）</td>
</tr>
<tr>
<td>help @[数据类型]</td>
<td>查看相关数据类型的命令</td>
</tr>
<tr>
<td>help [commend]</td>
<td>查询相关命令的用法</td>
</tr>
<tr>
<td>keys [条件]</td>
<td>查看符合模板的所有key，不建议在生产环境设备上使用</td>
</tr>
<tr>
<td>expire [key] [time]</td>
<td>给一个key设置有效期，到期时会被自动删除；创建key时没有设置时间key将永久有效，表示为-1；</td>
</tr>
<tr>
<td>ttl [key]</td>
<td>查看一个KEY的剩余有效期</td>
</tr>
<tr>
<td>exists [key]</td>
<td>判断key是否存在</td>
</tr>
<tr>
<td>set [key] [value]</td>
<td><strong>添加或者修改</strong>已经存在的一个String类型的键值对</td>
</tr>
<tr>
<td>set [key] [value] ex [time]</td>
<td>组合命令，添加一个的键值对，并且指定有效期(单位秒)</td>
</tr>
<tr>
<td>get [key]</td>
<td>获取指定 key 的值</td>
</tr>
<tr>
<td>mset [key1] [value1] …</td>
<td>批量添加多个键值对</td>
</tr>
<tr>
<td>mget [key1] [key2] …..</td>
<td>根据多个key获取多个String类型的value</td>
</tr>
<tr>
<td>setnx [key] [value]</td>
<td>添加一个String类型的键值对，前提是这个key不存在，否则不执行</td>
</tr>
<tr>
<td>setex [key] [time] [value]</td>
<td>添加一个String类型的键值对，并且指定有效期(单位秒)</td>
</tr>
<tr>
<td>del [key1] [key2]…..</td>
<td>删除一个指定的key,或删除多个key</td>
</tr>
<tr>
<td>flushdb</td>
<td>当前数据库中的所有Key</td>
</tr>
<tr>
<td>flushall</td>
<td>所有数据库中的key</td>
</tr>
<tr>
<td>incr [key]</td>
<td>让一个整型的key自增1,返回增加1后的值</td>
</tr>
<tr>
<td>incrby [key] [增长数]</td>
<td>让一个整型的key自增并指定步长,返回增加1个步长后的值</td>
</tr>
<tr>
<td>decr [key]</td>
<td>将 key 中储存的数字值减一</td>
</tr>
<tr>
<td>decr key [增长数]</td>
<td>key 所储存的值减去给定的减量值（decrement）</td>
</tr>
<tr>
<td>append [key] [value]</td>
<td>如果 key 已经存在并且是一个字符串，将指定的value 追加到该 key 原来值 value 的末尾</td>
</tr>
</tbody></table>
<ul>
<li><p>查看相关数据类型的命令</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">help <span class="variable">@hash</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>查询相关命令的用法</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">help keys</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看符合模板的所有key，不建议在生产环境设备上使用</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">keys <span class="operator">*</span>    # 查询所有的键</span><br><span class="line">keys a<span class="operator">*</span>   # 查询以a开头的键</span><br></pre></td></tr></table></figure>
</li>
<li><p>删除一个指定的key,或删除多个key</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">del k1 k2 k3</span><br></pre></td></tr></table></figure>
</li>
<li><p>判断key是否存在</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">exists</span> name</span><br></pre></td></tr></table></figure>
</li>
<li><p>给一个key设置有效期，有效期到期时该key会被自动删除；如果创建key时没有设置时间key将永久有效，表示为-1；</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">expire name <span class="number">20</span>   # (单位秒)</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看一个KEY的剩余有效期</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ttl name</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="3-String类型："><a href="#3-String类型：" class="headerlink" title="3.String类型："></a>3.String类型：</h3><ul>
<li><p>String类型，也就是字符串类型，时Redis中最简单的存储类型。</p>
</li>
<li><p>其中value是字符串，不过根据字符串的格式不同，又可以分为3类：</p>
<table>
<thead>
<tr>
<th>分类</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>string</td>
<td>普通字符串</td>
</tr>
<tr>
<td>int</td>
<td>整形类型，可以做自增，自减操作</td>
</tr>
<tr>
<td>float</td>
<td>浮点类型，可以做自增，自减操作</td>
</tr>
</tbody></table>
</li>
<li><p>不管是哪种格式，底层都是字节数组形式存储，只不过是编码方式不同。字符串类型的最大空间不能超过512m.</p>
</li>
<li><p>常见命令：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 添加或者修改一个String类型的键值对</span><br><span class="line"><span class="keyword">set</span> name itcast</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 添加或者修改一个String类型的键值对(多key结构)</span><br><span class="line"><span class="keyword">set</span> heima:<span class="keyword">user</span>:<span class="number">1</span> itcast</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 批量添加多个String类型的键值对</span><br><span class="line">mset k1 v1 k2 v2 k3 v3  </span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 根据多个key获取多个String类型的<span class="keyword">value</span></span><br><span class="line">mget k1 k2 k3</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 让一个整型的key自增<span class="number">1</span></span><br><span class="line">incr age</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 让一个整型的key自增并指定步长</span><br><span class="line">incrby age <span class="number">2</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 添加一个String类型的键值对，前提是这个key不存在；如果不存在不执行</span><br><span class="line">setnx lock <span class="number">1</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="4-Hash类型："><a href="#4-Hash类型：" class="headerlink" title="4.Hash类型："></a>4.Hash类型：</h3><ul>
<li><p>Hash类型，也叫散列，其value是一个无序字典，类似于Java中的HashMap结构</p>
</li>
<li><p>String结构是将对象序列化为JSON字符串后存储，当需要修改对象某个字段时很不方便</p>
<p><img src="C:\Users\user\AppData\Roaming\Typora\typora-user-images\image-20220602194019102.png" alt="image-20220602194019102"></p>
</li>
<li><p>Hash结构可以将对象中的每个字段独立存储，可以针对单个字段做CRUD：</p>
<p><img src="C:\Users\user\AppData\Roaming\Typora\typora-user-images\image-20220602194053153.png" alt="image-20220602194053153"></p>
</li>
<li><p>常用命令：</p>
<table>
<thead>
<tr>
<th>常用命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>hset [key] [field] [value]</td>
<td><strong>添加或者修改</strong>hash类型key的field的值</td>
</tr>
<tr>
<td>hget [key] [field]</td>
<td>获取一个hash类型key的field的值</td>
</tr>
<tr>
<td>hmset [key1] [field1] [value1] [field2] [value2]…</td>
<td>批量添加多个hash类型key的field的值</td>
</tr>
<tr>
<td>hmget [key1] [field1] [field2]…..</td>
<td>批量获取多个hash类型key的field的值</td>
</tr>
<tr>
<td>hgetall [key]</td>
<td>获取一个hash类型的key中的所有的field和value</td>
</tr>
<tr>
<td>hkeys [key]</td>
<td>获取一个hash类型的key中的所有的field</td>
</tr>
<tr>
<td>hvals [key]</td>
<td>获取一个hash类型的key中的所有的value</td>
</tr>
<tr>
<td>hincrby [key] [field] [time]</td>
<td>让一个hash类型key的字段值自增并指定步长，返回增长后的值</td>
</tr>
<tr>
<td>hsetnx [key] [field] [value]</td>
<td>添加一个hash类型的key的field值，前提是这个field不存在，否则不执行</td>
</tr>
</tbody></table>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 添加或者修改hash类型key的field的值</span><br><span class="line">hset heima:<span class="keyword">user</span>:<span class="number">1</span> name zhangsan	</span><br><span class="line">hset heima:<span class="keyword">user</span>:<span class="number">1</span> age <span class="number">18</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 获取一个hash类型key的field的值</span><br><span class="line">hget heima:<span class="keyword">user</span>:<span class="number">3</span> age</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 获取一个hash类型的key中的所有的field和<span class="keyword">value</span></span><br><span class="line">hgetall heima:<span class="keyword">user</span>:<span class="number">3</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 获取一个hash类型的key中的所有的field</span><br><span class="line">hkeys heima:<span class="keyword">user</span>:<span class="number">3</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 让一个hash类型key的字段值自增并指定步长，返回增长后的值</span><br><span class="line">hincrby heima:<span class="keyword">user</span>:<span class="number">3</span> age <span class="number">2</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="5-List类型："><a href="#5-List类型：" class="headerlink" title="5.List类型："></a>5.List类型：</h3><ul>
<li><p>Redis中的List类型与Java中的LinkedList类似，可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。</p>
</li>
<li><p>特征也与LinkedList类似：</p>
<ol>
<li>有序  2.元素可以重复  3.插入和删除快  4.查询速度一般</li>
</ol>
</li>
<li><p>常用来存储一个有序数据，例如：朋友圈点赞列表，评论列表等。</p>
</li>
<li><p>常用命令：</p>
<table>
<thead>
<tr>
<th>常见命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>lpush [key] [value2] [value2]….</td>
<td>向列表左侧插入一个或多个元素，返回链表长度</td>
</tr>
<tr>
<td>lpop [key]</td>
<td>移除并返回列表左侧的第一个元素，没有则返回null</td>
</tr>
<tr>
<td>rpush  [key] [value2] [value2]….</td>
<td>向列表右侧插入一个或多个元素，返回链表长度</td>
</tr>
<tr>
<td>rpop</td>
<td>移除并返回列表右侧的第一个元素</td>
</tr>
<tr>
<td>lrange [key] [start] [end]</td>
<td>返回一段角标范围内的所有元素，从零开始[ start end )</td>
</tr>
<tr>
<td>blpop [key] [time]</td>
<td>移除并返回列表左侧的第一个元素，只不过在没有元素时等待指定时间(单位秒)</td>
</tr>
<tr>
<td>brpop [key] [time]</td>
<td>移除并返回列表右侧的第一个元素，只不过在没有元素时等待指定时间(单位秒)</td>
</tr>
</tbody></table>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 向列表左侧插入一个或多个元素(顺序为<span class="number">3</span><span class="number">-2</span><span class="number">-1</span>)</span><br><span class="line">lpush users <span class="number">1</span> <span class="number">2</span> <span class="number">3</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 向列表右侧插入一个或多个元素(顺序为<span class="number">1</span><span class="number">-2</span><span class="number">-3</span>)</span><br><span class="line">rpush users <span class="number">1</span> <span class="number">2</span> <span class="number">3</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 移除并返回列表左侧的第一个元素</span><br><span class="line">lpop users </span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 返回一段角标范围内的所有元素，[ <span class="keyword">start</span> <span class="keyword">end</span> )</span><br><span class="line">lrange users <span class="number">0</span> <span class="number">2</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 移除并返回列表左侧的第一个元素，只不过在没有元素时等待指定时间(单位秒)</span><br><span class="line">blpop users <span class="number">10</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="6-集合类型-set："><a href="#6-集合类型-set：" class="headerlink" title="6.集合类型 set："></a>6.集合类型 set：</h3><ul>
<li><p>Redis的Set结构与Java中的HashSet类似，可以看做是一个value为null的HashMap。因为也是一个hash表，因此具备与HashSet类似的特征：</p>
</li>
<li><p>特点：</p>
<ol>
<li>无序  2.元素不可重复  3.查找快  4.支持交集、并集、差集等功能</li>
</ol>
</li>
<li><p>常见命令：</p>
<table>
<thead>
<tr>
<th>常见命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>sadd [key] [value1] [value2]….</td>
<td>向set中添加一个或多个元素</td>
</tr>
<tr>
<td>srem [key] [value]</td>
<td>移除set中的指定元素</td>
</tr>
<tr>
<td>scard [key]</td>
<td>返回set中元素的个数</td>
</tr>
<tr>
<td>sismember [key] [value]</td>
<td>判断一个元素是否存在于set中，如果存在返回1</td>
</tr>
<tr>
<td>smembers [key]</td>
<td>获取set中的所有元素</td>
</tr>
<tr>
<td>sinter [key1] [key2]</td>
<td>求key1与key2的交集，返回相同的元素</td>
</tr>
<tr>
<td>sdiff [key1] [key2]</td>
<td>求key1与key2的差集，返回key1中不相同的元素</td>
</tr>
<tr>
<td>sunion [key1] [key2]</td>
<td>求key1和key2的并集，返回所有的元素（不重复）</td>
</tr>
</tbody></table>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 向<span class="keyword">set</span>中添加一个或多个元素</span><br><span class="line">sadd users a b c d</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 移除<span class="keyword">set</span>中的指定元素</span><br><span class="line">srem users a</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 返回<span class="keyword">set</span>中元素的个数</span><br><span class="line">scard users</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 判断一个元素是否存在于<span class="keyword">set</span>中</span><br><span class="line">sismember users a</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 获取<span class="keyword">set</span>中的所有元素</span><br><span class="line">smembers users</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 求key1与key2的交集，返回相同的元素</span><br><span class="line">sinter users products</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="7-有序集合类型-sortedset："><a href="#7-有序集合类型-sortedset：" class="headerlink" title="7.有序集合类型 sortedset："></a>7.有序集合类型 sortedset：</h3><ul>
<li><p>Redis的SortedSet是一个可排序的set集合，与Java中的TreeSet有些类似，但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性，可以基于score属性对元素排序，底层的实现是一个跳表（SkipList）加 hash表</p>
</li>
<li><p>SortedSet具备下列特性：</p>
<ol>
<li>可排序  2.元素不重复  3.查询速度快</li>
</ol>
</li>
<li><p>因为SortedSet的可排序特性，经常被用来实现排行榜这样的功能。</p>
</li>
<li><p>注意：所有的排名默认都是升序，如果要降序则在命令的Z后面添加REV即可</p>
</li>
<li><p>注意：score为相同数据类型</p>
</li>
<li><p>常用命令：</p>
<table>
<thead>
<tr>
<th>常用命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>zadd [key] [score1] [value1] [score2] [value2]….</td>
<td>添加一个或多个元素到sorted set ，如果已经存在则更新其score值</td>
</tr>
<tr>
<td>zrem [key] [value]</td>
<td>删除sorted set中的一个指定元素</td>
</tr>
<tr>
<td>zscore [key] [value]</td>
<td>获取sorted set中的指定元素的score值</td>
</tr>
<tr>
<td>zrank [key] [value]</td>
<td>获取sorted set 中的指定元素的排名，从零开始</td>
</tr>
<tr>
<td>zcard [key]</td>
<td>获取sorted set中的元素个数</td>
</tr>
<tr>
<td>zcount [key] [min] [max]</td>
<td>统计score值在给定范围内的所有元素的个数，包括min和max</td>
</tr>
<tr>
<td>zrange [key] [start] [stop]</td>
<td>按照score排序后，获取指定排名范围内的元素，包括start和stop</td>
</tr>
<tr>
<td>zincrby [key] [increment] [value]</td>
<td>让sorted set中的指定元素自增，步长为指定的increment值</td>
</tr>
<tr>
<td>zrangebyscore [key] [min] [max]</td>
<td>按照score排序后，获取指定score范围内的元素，包括min和max</td>
</tr>
<tr>
<td>zdiff，zinter，zunion</td>
<td>求差集、交集、并集</td>
</tr>
</tbody></table>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 添加一个或多个元素到sorted <span class="keyword">set</span> ，如果已经存在则更新其score值</span><br><span class="line">zadd stus <span class="number">85</span> jack <span class="number">45</span> lucy <span class="number">98</span> rose <span class="number">68</span> wangsan</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 删除sorted <span class="keyword">set</span>中的一个指定元素</span><br><span class="line">zrem stus jack</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 获取sorted <span class="keyword">set</span>中的指定元素的score值</span><br><span class="line">zscore stus jack</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 获取sorted <span class="keyword">set</span> 中的指定元素的排名，从零开始</span><br><span class="line">zrank stus lucy   # 升序</span><br><span class="line">zrevrank stus jack  # 降序</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 获取sorted <span class="keyword">set</span>中的元素个数</span><br><span class="line">zcard stus</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 统计score值在给定范围内的所有元素的个数</span><br><span class="line">zcount stus <span class="number">45</span> <span class="number">85</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 按照score排序后，获取指定排名范围内的元素</span><br><span class="line">zrange stus <span class="number">0</span> <span class="number">1</span>  # 升序</span><br><span class="line">zrevrange stus <span class="number">0</span> <span class="number">1</span>  # 降序 </span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 让sorted <span class="keyword">set</span>中的指定元素自增，步长为指定的increment值</span><br><span class="line">zincrby stus <span class="number">2</span> jack</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 按照score排序后，获取指定score范围内的元素</span><br><span class="line">zrangebyscore stus <span class="number">45</span> <span class="number">87</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="8-位操作Bitmaps："><a href="#8-位操作Bitmaps：" class="headerlink" title="8.位操作Bitmaps："></a>8.位操作Bitmaps：</h3><ul>
<li><p>Bitmaps 本身不是一种数据类型， 实际上它就是字符串（key-value） ， 但是它可以对字符串的<strong>位进行操作</strong></p>
</li>
<li><p>Bitmaps 单独提供了一套命令， 所以在 Redis 中使用 Bitmaps 和使用字符串的方法不太相同。 可以把 Bitmaps 想象成一个以位为单位的数组， 数组的每个单元只能存储 0 和 1， 数组的下标在 Bitmaps 中叫做偏移量</p>
</li>
<li><p>实例：存储网站每天访问次数</p>
</li>
<li><p>语法：</p>
<table>
<thead>
<tr>
<th>bitmaps命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>setbit [key] [offset] [value]</td>
<td>设置Bitmaps中某个偏移量的值（只能是0或1），offset默认从0开始偏移</td>
</tr>
<tr>
<td>getbit [key] [offset]</td>
<td>获取Bitmaps中某个偏移量的值</td>
</tr>
<tr>
<td>bitcount [key] [start end]</td>
<td>返回字符串被设置为1的个数，例：100001中有2个1</td>
</tr>
</tbody></table>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">setbit users:<span class="number">20210101</span> <span class="number">1</span> <span class="number">1</span>    <span class="comment">-- 1</span></span><br><span class="line">setbit users:<span class="number">20210101</span> <span class="number">6</span> <span class="number">1</span>    <span class="comment">-- 100000</span></span><br><span class="line">setbit users:<span class="number">20210101</span> <span class="number">11</span> <span class="number">1</span>   <span class="comment">-- 10000000000</span></span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">getbit users:<span class="number">20210101</span> <span class="number">6</span>      <span class="comment">-- 获取第6位上的1</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="9-基数统计HyperLog："><a href="#9-基数统计HyperLog：" class="headerlink" title="9.基数统计HyperLog："></a>9.基数统计HyperLog：</h3><ul>
<li><p>Redis HyperLogLog 是用来做<strong>基数统计</strong>的算法</p>
</li>
<li><p>基数：一个集合中，不重复的数</p>
</li>
<li><p>HyperLogLog 的优点是：在输入元素的数量或者体积非常非常大时，计算基数所需的空间总是固定的、并且是很小的</p>
</li>
<li><p>在 Redis 里面，每个 HyperLogLog 键只需要花费 12 KB 内存，就可以计算接近 2^64 个不同元素的基数。这和计算基数时，元素越多耗费内存就越多的集合形成鲜明对比</p>
</li>
<li><p>但是，因为 HyperLogLog 只会根据输入元素来计算基数，而不会储存输入元素本身，所以 HyperLogLog 不能像集合那样，返回输入的各个元素</p>
</li>
<li><p>语法：</p>
<table>
<thead>
<tr>
<th>HyperLog命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>pfadd [key] [value…..]</td>
<td>向key集合中加入value，添加成功返回1，否则返回0</td>
</tr>
<tr>
<td>pfcount [key…..]</td>
<td>统计所选集合们中不重复的个数（所有集合值加在一起不重复）</td>
</tr>
<tr>
<td>pfmerge [destkey] [sourcekey…..]</td>
<td>将sourcekey集合们的值合并到destkey集合</td>
</tr>
</tbody></table>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pfadd program &quot;java&quot;</span><br><span class="line">pfadd program &quot;java&quot; &quot;C++&quot;</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pfcount program</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pfmerge hll3 hll1 hll2</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="10-经纬度GEO："><a href="#10-经纬度GEO：" class="headerlink" title="10.经纬度GEO："></a>10.经纬度GEO：</h3><ul>
<li><p>Redis 3.2 中增加了对 GEO 类型的支持。GEO，Geographic，地理信息的缩写。该类型，就是元素的 2 维坐标，在地图上就是经纬度。</p>
</li>
<li><p>redis 基于该类型，提供了经纬度设置，查询，范围查询，距离查询，经纬度 Hash 等常见操作</p>
</li>
<li><p>语法：</p>
<table>
<thead>
<tr>
<th>GEO命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>geoadd [key] [longitude] [latitude] [name]…</td>
<td>添加地理位置信息到key集合，longitude经度，latitude维度，name名称</td>
</tr>
<tr>
<td>geopos [key] [name]</td>
<td>获取key集合中name的经纬度</td>
</tr>
<tr>
<td>geodist [key] [name1] [name2]</td>
<td>获取两个位置之间的之直线距离</td>
</tr>
<tr>
<td>georadius [key] [longitude] [latitude] [num] [unit]</td>
<td>获取以给定经纬度为中心，num长度，unit单位的半径内的元素</td>
</tr>
</tbody></table>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">geoadd china:city <span class="number">121.47</span> <span class="number">31.23</span> shanghai</span><br><span class="line">geoadd china:city <span class="number">121.47</span> <span class="number">31.23</span> shanghai china:city <span class="number">121.47</span> <span class="number">31.23</span> shanghai</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">geopos china:city shanghai</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">geopos china:city shanghai beijing</span><br></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">geoadd china:city <span class="number">121.47</span> <span class="number">31.23</span> <span class="number">1000</span> km</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="5-Redis的配置文件"><a href="#5-Redis的配置文件" class="headerlink" title="5.Redis的配置文件:"></a>5.Redis的配置文件:</h2><h3 id="1-Units："><a href="#1-Units：" class="headerlink" title="1.Units："></a>1.Units：</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置大小单位，开头定义了一些基本的度量单位，只支持 bytes，不支持 bit。大小写不敏感。</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1k =&gt; 1000 bytes</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1kb =&gt; 1024 bytes</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1m =&gt; 1000000 bytes</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1mb =&gt; 1024*1024 bytes</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1g =&gt; 1000000000 bytes</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1gb =&gt; 1024*1024*1024 bytes</span></span><br></pre></td></tr></table></figure>

<h3 id="2-network："><a href="#2-network：" class="headerlink" title="2.network："></a>2.network：</h3><ul>
<li><p>bind：默认情况下 bind&#x3D;127.0.0.1 只能接受本机的访问请求。在不写的情况下，无限制接受任何 IP 地址的访问。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bind 127.0.0.1</span><br></pre></td></tr></table></figure>
</li>
<li><p>protected-mode：如果开启了protected-mode，那么在没有设定bind ip且没有设密码的情况下，Redis只允许接受本机的响应。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">protected-mode no</span><br></pre></td></tr></table></figure>
</li>
<li><p>tcp-backlog：设置 tcp 的 backlog，backlog 其实是一个连接队列，backlog队列总和 &#x3D; 未完成三次握手队列 + 已经完成三次握手队列。在高并发环境下你需要一个高 backlog 值来避免慢客户端连接问题。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tcp-backlog 511</span><br></pre></td></tr></table></figure>
</li>
<li><p>timeout：一个空闲的客户端维持多少秒会关闭，0表示关闭该功能。即永不关闭。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">timeout 0</span><br></pre></td></tr></table></figure>
</li>
<li><p>tcp-keepalive：对访问客户端的一种心跳检测，每 n 秒检测一次。单位为秒，如果设置为0，则不会进行 Keepalive 检测，建议设置成 60。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tcp-keepalive 0</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="3-general："><a href="#3-general：" class="headerlink" title="3.general："></a>3.general：</h3><ul>
<li><p>daemonize：是否为后台进程，即守护进程，用于后台启动，设置为yes。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">daemonize yes</span><br></pre></td></tr></table></figure>
</li>
<li><p>pidfile：存放pid文件的位置，每个实例会产生一个不同的pid文件。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pidfile /var/run/redis_6379.pid</span><br></pre></td></tr></table></figure>
</li>
<li><p>loglevel：指定日志记录级别，Redis 总共支持四个级别：debug、verbose、notice、warning，默认为notice。四个级别根据使用阶段来选择，生产环境选择 notice 或者warning。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">loglevel notice</span><br></pre></td></tr></table></figure>
</li>
<li><p>logfile：日志文件名称</p>
</li>
</ul>
  <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">logfile &quot;&quot;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>databases：设定库的数量，默认16，默认数据库为0，可以使用 SELECT <dbid> 命令在连接上指定数据库id。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">databases 16</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="4-security："><a href="#4-security：" class="headerlink" title="4.security："></a>4.security：</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 设置密码</span><br><span class="line">requirepass 123456</span><br></pre></td></tr></table></figure>

<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; config get requirepass             # 查看密码</span><br><span class="line">1) &quot;requirepass&quot;</span><br><span class="line">2) &quot;&quot;</span><br><span class="line">127.0.0.1:6379&gt; config set requirepass &quot;123456&quot;    # 设置密码（临时）</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; auth 123456                        # 登录</span><br><span class="line">OK</span><br></pre></td></tr></table></figure>

<h3 id="5-clients："><a href="#5-clients：" class="headerlink" title="5.clients："></a>5.clients：</h3><ul>
<li><p>maxclients：设置redis同时可以与多少个客户端进行连接。默认情况下为10000个客户端。如果达到了此限制，redis则会拒绝新的连接请求，并且向这些连接请求方发出“max number of clients reached”以作回应。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">maxclients 10000</span><br></pre></td></tr></table></figure>
</li>
<li><p>maxmemory：建议必须设置，否则可能导致将内存占满，造成服务器宕机。设置redis可以使用的内存量。一旦到达内存使用上限，redis将会试图移除内部数据，移除规则可以通过maxmemory-policy来指定。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">maxmemory [字节数]</span><br></pre></td></tr></table></figure>
</li>
<li><p>maxmemory-policy：设置内存达到使用上限后的移除规则</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>volatile-lru</td>
<td>使用LRU算法移除key，只对设置了过期时间的键；（最近最少使用）</td>
</tr>
<tr>
<td>allkeys-lru</td>
<td>在所有集合key中，使用LRU算法移除key</td>
</tr>
<tr>
<td>volatile-random</td>
<td>在过期集合中移除随机的key，只对设置了过期时间的键</td>
</tr>
<tr>
<td>allkeys-random</td>
<td>在所有集合key中，移除随机的key</td>
</tr>
<tr>
<td>volatile-ttl</td>
<td>移除那些TTL值最小的key，即那些最近要过期的key</td>
</tr>
<tr>
<td>noeviction</td>
<td>不进行移除。针对写操作，只是返回错误信息</td>
</tr>
</tbody></table>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">maxmemory-policy noeviction</span><br></pre></td></tr></table></figure>
</li>
<li><p>maxmemory-samples：用于设置样本数量，LRU算法和最小TTL算法都并非是精确的算法一般设置3到7的数字，数值越小样本越不准确，但性能消耗越小</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">maxmemory-samples 5</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="6-Redis发布与订阅："><a href="#6-Redis发布与订阅：" class="headerlink" title="6.Redis发布与订阅："></a>6.Redis发布与订阅：</h2><ul>
<li><p>概念：Redis发布订阅（pub&#x2F;sub）是一种消息通信模式：发送者（pub）发送消息，订阅者（sub）接收消息</p>
</li>
<li><p>命令行实现：</p>
<ol>
<li><p>打开一个客户端订阅channell：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">subscribe [订阅名]</span><br></pre></td></tr></table></figure>
</li>
<li><p>打开另一个客户端，给channell发布消息hello</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">publish [订阅名] hello    <span class="comment">-- 返回当前订阅者数量</span></span><br></pre></td></tr></table></figure></li>
</ol>
</li>
</ul>
<h2 id="7-事务管理："><a href="#7-事务管理：" class="headerlink" title="7.事务管理："></a>7.事务管理：</h2><h3 id="1-事务定义："><a href="#1-事务定义：" class="headerlink" title="1.事务定义："></a>1.事务定义：</h3><ul>
<li>Redis 事务是一个单独的隔离操作：事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中，不会被其他客户端发送来的命令请求所打断。</li>
<li>Redis 事务的主要作用就是串联多个命令防止别的命令插队。</li>
</ul>
<h3 id="2-Multi、Exec、discard："><a href="#2-Multi、Exec、discard：" class="headerlink" title="2.Multi、Exec、discard："></a>2.Multi、Exec、discard：</h3><ul>
<li><p>Multi：从输入 Multi 命令开始，输入的命令都会依次进入命令队列中，但不会执行，直到输入 Exec 后，Redis会将之前的命令队列中的命令依次执行组队的过程中可以通过 discard 来放弃组队。</p>
</li>
<li><p>使用：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; multi</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; set k1 v1</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; set k2 v2</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; exec</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="3-事务的错误处理："><a href="#3-事务的错误处理：" class="headerlink" title="3.事务的错误处理："></a>3.事务的错误处理：</h3><ul>
<li>组队中某个命令出现了报告错误，执行时整个的所有队列都会被取消。</li>
<li>如果执行阶段某个命令报出了错误，则只有报错的命令不会被执行，而其他的命令都会执行，不会回滚。</li>
</ul>
<h3 id="4-事务的冲突问题："><a href="#4-事务的冲突问题：" class="headerlink" title="4.事务的冲突问题："></a>4.事务的冲突问题：</h3><ul>
<li><p>悲观锁：</p>
<ul>
<li>悲观锁(Pessimistic Lock)顾名思义，就是很悲观，每次去拿数据的时候都认为别人会修改，所以每次在拿数据的时候都会上锁</li>
</ul>
</li>
<li><p>乐观锁：</p>
<ul>
<li>乐观锁(Optimistic Lock)顾名思义，就是很乐观，每次去拿数据的时候都认为别人不会修改，所以不会上锁</li>
<li>但是在更新的时候会判断一下在此期间别人有没有去更新这个数据</li>
<li>乐观锁适用于多读的应用类型，这样可以提高吞吐量</li>
<li>Redis就是利用这种check-and-set机制实现事务的</li>
</ul>
</li>
<li><p>watch：</p>
<ul>
<li><p>在执行 multi 之前，先执行 watch key1 [key2] 可以监视一个(或多个) key ，如果在事务执行之前这个&#x2F;些 key 被其他命令所改动，那么事务将被打断。</p>
</li>
<li><p>示例：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">客户端A：</span></span><br><span class="line">127.0.0.1:6379&gt; watch balance</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; multi</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; decrby balance 8000</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; exec</span><br><span class="line">1) (integer) 2000</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">客户端B：</span></span><br><span class="line">127.0.0.1:6379&gt; watch balance</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; multi</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; incrby balance 2000</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; exec</span><br><span class="line">1) (nil)      # 客户端B没有修改成功</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>unwatch：</p>
<ul>
<li>用于取消 WATCH 命令对所有 key 的监视。</li>
<li>如果在执行 WATCH 命令之后，EXEC 命令或DISCARD 命令先被执行了的话，那么就不需要再执行UNWATCH 了。</li>
</ul>
</li>
<li><p><strong>事务三特性</strong>：</p>
<ul>
<li>单独的隔离操作：<ul>
<li>事务中的所有命令都会序列化、按顺序地执行</li>
<li>事务在执行的过程中，不会被其他客户端发送来的命令请求所打断。</li>
</ul>
</li>
<li>没有隔离级别的概念：队列中的命令没有提交之前都不会实际被执行，因为事务提交前任何指令都不会被实际执行。</li>
<li>不保证原子性：事务中如果有一条命令执行失败，其后的命令仍然会被执行，没有回滚。</li>
</ul>
</li>
</ul>
<h2 id="8-数据持久化："><a href="#8-数据持久化：" class="headerlink" title="8.数据持久化："></a>8.数据持久化：</h2><h3 id="1-分类："><a href="#1-分类：" class="headerlink" title="1.分类："></a>1.分类：</h3><ul>
<li>Redis提供了主要提供了 2 种不同形式的持久化方式：<ul>
<li>RDB（Redis数据库）：RDB全称Redis Database Backup file（Redis数据备份文件），也被叫做<strong>Redis数据快照</strong>。</li>
<li>AOF（Append Only File）：AOF 持久化记录服务器接收到的每个<strong>写操作</strong>，在服务器启动时再次播放，重建原始数据集。 命令使用与 Redis 协议本身相同的格式以仅附加方式记录。 当日志变得太大时，Redis 能够在后台重写日志。</li>
</ul>
</li>
</ul>
<h3 id="2-RDB持久化："><a href="#2-RDB持久化：" class="headerlink" title="2.RDB持久化："></a>2.RDB持久化：</h3><ul>
<li><p>Redis会单独创建（fork）一个子进程来进行持久化化，会先将数据写入到 一个临时文件中，待持久化过程都结束后，再用这个临时文件替换上次持久化好的文件。</p>
</li>
<li><p>整个过程中，主进程是不进行任何IO操作的，这就确保了极高的性能</p>
</li>
<li><p><strong>Redis默认支持</strong>，不许需要进行配置，默认就使用这种机制</p>
</li>
<li><p>快照文件称为.rdb文件，默认是保存在当前运行目录。</p>
</li>
<li><p>如果需要进行大规模数据的恢复，且对于数据恢复的完整性不是非常敏感，那RDB方式要比AOF方式更加的高效。</p>
</li>
<li><p>RDB的缺点是最后一次持久化后的数据可能丢失。</p>
</li>
<li><p>Fork：</p>
<ul>
<li>作用：<strong>复制一个与当前进程一样的进程。</strong></li>
<li>在 Linux 程序中，fork() 会产生一个和父进程完全相同的子进程，但子进程在此后多会 exec 系统调用，出于效率考虑，Linux 中引入了“<strong>写时复制技术</strong>”。</li>
</ul>
</li>
<li><p>当主进程执行读操作时，访问共享内存；</p>
</li>
<li><p>当主进程执行写操作时，则会拷贝一份数据，执行写操作。</p>
</li>
<li><p>RDB方式bgsave的基本流程：</p>
<ol>
<li>fork主进程得到一个子进程，共享内存空间</li>
<li>子进程读取内存数据并写入新的RDB文件</li>
<li>用新RDB文件替换旧的RDB文件</li>
</ol>
</li>
<li><p>RDB的优缺点：</p>
<ul>
<li>优点：<ul>
<li>适合大规模的备份</li>
<li>节省磁盘空间</li>
<li>恢复速度快</li>
</ul>
</li>
<li>缺点：<ul>
<li>RDB执行间隔时间长</li>
<li>两次RDB之间写入数据有丢失的风险</li>
<li>fork子进程、压缩、写出RDB文件都比较耗时</li>
</ul>
</li>
</ul>
</li>
<li><p>RDB持久化的配置：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">dbfilename dump.rdb                # 快照将被写入dbfilename指定的文件中（默认是dump.rdb文件）</span><br><span class="line">dir &quot;./&quot;                           # 配置文件路径</span><br><span class="line">stop<span class="operator">-</span>writes<span class="operator">-</span><span class="keyword">on</span><span class="operator">-</span>bgsave<span class="operator">-</span>error yes    # 当 Redis 无法写入磁盘的话，直接关掉 Redis 的写操作，推荐配置为 yes。</span><br><span class="line">rdbcompression yes                 # 是否进行压缩存储,如果你不想消耗CPU来进行压缩的话，可以设置为关闭此功能</span><br><span class="line">rdbchecksum yes                    # </span><br></pre></td></tr></table></figure>
</li>
<li><p>RDB持久化在四种情况下会执行：</p>
<ol>
<li><p>执行save命令：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">save   <span class="comment">-- 由Redis主线程来执行RDB，会阻塞所有命令</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>执行bgsave命令（推荐使用）：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bgsave   <span class="comment">-- 开启子进程执行RDB，避免主进程受到影响</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>Redis停机时：Redis停机时会执行一次save命令，实现RDB持久化</p>
</li>
<li><p>触发RDB条件时</p>
<ul>
<li><p>Redis内部有触发RDB的机制，可以在redis.conf文件中找到，格式如下：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># <span class="number">900</span>秒内，如果至少有<span class="number">1</span>个key被修改，则执行bgsave ， 如果是save &quot;&quot; 则表示禁用RDB</span><br><span class="line">save <span class="number">900</span> <span class="number">1</span>   </span><br><span class="line">save <span class="number">300</span> <span class="number">10</span>  </span><br><span class="line">save <span class="number">60</span> <span class="number">10000</span> </span><br></pre></td></tr></table></figure>
</li>
<li><p>RDB的其它配置也可以在redis.conf文件中设置：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 是否压缩 ,建议不开启，压缩也会消耗cpu，磁盘的话不值钱</span><br><span class="line">rdbcompression yes</span><br><span class="line"></span><br><span class="line"># RDB文件名称</span><br><span class="line">dbfilename dump.rdb  </span><br><span class="line"></span><br><span class="line"># 文件保存的路径目录</span><br><span class="line">dir .<span class="operator">/</span> </span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ol>
</li>
</ul>
<h3 id="3-AOF持久化："><a href="#3-AOF持久化：" class="headerlink" title="3.AOF持久化："></a>3.AOF持久化：</h3><ul>
<li><p>AOF全称为Append Only File（追加文件）。</p>
</li>
<li><p>Redis处理的每一个写命令（<strong>写操作</strong>）都会记录在AOF文件， <strong>只许追加文件</strong>但不可以改写文件，可以看做是<strong>命令日志文件</strong>。</p>
</li>
<li><p>redis 启动之初会读取该文件重新构建数据</p>
</li>
<li><p>持久化流程：</p>
<ul>
<li><p>图示：</p>
<p><img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230219195610182.png" alt="image-20230219195610182"></p>
</li>
</ul>
<ol>
<li>客户端的请求写命令会被 append 追加到 AOF 缓冲区内。</li>
<li>AOF 缓冲区根据 AOF 持久化策略 [always,everysec,no] 将操作sync同步到磁盘的 AOF 文件中。</li>
<li>AOF 文件大小超过重写策略或手动重写时，会对 AOF 文件 rewrite 重写，压缩 AOF 文件容量。</li>
<li>Redis 服务重启时，会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的。</li>
</ol>
</li>
<li><p>AOF配置：</p>
<ul>
<li><p>需要修改redis.conf配置文件来禁用RDB</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">save <span class="number">900</span> <span class="number">1</span> </span><br><span class="line">.......   </span><br><span class="line">save <span class="string">&quot;&quot;</span>     <span class="comment">//禁用RBD</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>AOF默认是关闭的，需要修改redis.conf配置文件来开启AOF：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 是否开启AOF功能，默认是no</span><br><span class="line">appendonly yes</span><br><span class="line"># AOF文件的名称</span><br><span class="line">appendfilename <span class="string">&quot;appendonly.aof&quot;</span>  </span><br></pre></td></tr></table></figure>
</li>
<li><p>AOF的命令记录的频率也可以通过redis.conf文件来配：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 方案一：表示每执行一次写命令，立即记录到AOF文件</span><br><span class="line">appendfsync always </span><br><span class="line"># 方案二：写命令执行完先放入AOF缓冲区，然后表示每隔<span class="number">1</span>秒将缓冲区数据写到AOF文件，是默认方案</span><br><span class="line">appendfsync everysec </span><br><span class="line"># 方案三：写命令执行完先放入AOF缓冲区，由操作系统决定何时将缓冲区内容写回磁盘</span><br><span class="line">appendfsync <span class="keyword">no</span></span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th>配置项</th>
<th>刷盘时机</th>
<th>优点</th>
<th>缺点</th>
</tr>
</thead>
<tbody><tr>
<td>Always</td>
<td>同步刷盘</td>
<td>可靠性高，几乎不丢数据</td>
<td>性能影响大</td>
</tr>
<tr>
<td>everysec</td>
<td>每秒刷盘</td>
<td>性能适中</td>
<td>最多丢失1秒数据</td>
</tr>
<tr>
<td>no</td>
<td>操作系统控制</td>
<td>性能最好</td>
<td>可靠性较差，可能丢失大量数据</td>
</tr>
</tbody></table>
</li>
</ul>
</li>
<li><p>AOF文件重写（Rewrite压缩）：</p>
<ul>
<li><p>因为是记录命令，AOF文件会比RDB文件大的多。</p>
</li>
<li><p>而且AOF会记录对同一个key的多次写操作，但只有最后一次写操作才有意义。</p>
</li>
<li><p>重写流程：</p>
<ul>
<li>图示：</li>
</ul>
<img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230219201126441.png" alt="image-20230219201126441" style="zoom:67%;" />

<ol>
<li>bgrewriteaof触发重写，判断是否当前有bgsave或bgrewriteaof在运行，如果有，则等待该命令结束后再继续执行。</li>
<li>主进程fork出子进程执行重写操作，保证主进程不会阻塞。</li>
<li>子进程遍历redis内存中数据到临时文件，客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。</li>
<li>子进程写完新的AOF文件后，向主进程发信号，父进程更新统计信息。主进程把aof_rewrite_buf中的数据写入到新的AOF文件。</li>
<li>使用新的AOF文件覆盖旧的AOF文件，完成AOF重写。</li>
</ol>
</li>
<li><p>通过执行bgrewriteaof命令，可以让AOF文件执行重写功能，用最少的命令达到相同效果。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bgrewriteaof</span><br></pre></td></tr></table></figure>
</li>
<li><p>Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># AOF文件比上次文件 增长超过多少百分比则触发重写</span><br><span class="line">auto<span class="operator">-</span>aof<span class="operator">-</span>rewrite<span class="operator">-</span>percentage <span class="number">100</span></span><br><span class="line"># AOF文件体积最小多大以上才触发重写 </span><br><span class="line">auto<span class="operator">-</span>aof<span class="operator">-</span>rewrite<span class="operator">-</span>min<span class="operator">-</span>size <span class="number">64</span>mb </span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>AOF的优缺点：</p>
<ul>
<li>优点：<ul>
<li>备份机制更稳健，丢失数据概率更低。</li>
<li>可读的日志文本，通过操作AOF稳健，可以处理误操作。</li>
</ul>
</li>
<li>缺点：<ul>
<li>比起RDB占用更多的磁盘空间。</li>
<li>恢复备份速度要慢。</li>
<li>每次读写都同步的话，有一定的性能压力。</li>
<li>存在个别Bug，造成恢复不能。</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="4-RDB与AOF的对比："><a href="#4-RDB与AOF的对比：" class="headerlink" title="4.RDB与AOF的对比："></a>4.RDB与AOF的对比：</h3><table>
<thead>
<tr>
<th></th>
<th>RDB</th>
<th>AOF</th>
</tr>
</thead>
<tbody><tr>
<td>持久化</td>
<td>定时对整个内存做快照</td>
<td>记录每一次执行的命令</td>
</tr>
<tr>
<td>数据完整性</td>
<td>不完整，两次备份之间会丢失</td>
<td>相对完整，取决于刷盘策略</td>
</tr>
<tr>
<td>文件大小</td>
<td>会有压缩，文件体积小</td>
<td>记录命令，文件体积很大</td>
</tr>
<tr>
<td>宕机恢复速度</td>
<td>很快</td>
<td>慢</td>
</tr>
<tr>
<td>数据恢复优先级</td>
<td>低，因为数据完整性不如AOF</td>
<td>高，因为数据完整性更高</td>
</tr>
<tr>
<td>系统资源占用</td>
<td>高，大量CPU和内存消耗</td>
<td>低，主要是磁盘IO资源，AOF重写占用大量CPU和内存资源</td>
</tr>
<tr>
<td>使用场景</td>
<td>可以容忍数分钟的数据丢失，追求更快的启动速度</td>
<td>对数据安全性要求较高</td>
</tr>
</tbody></table>
<h2 id="9-Redish的主从复制："><a href="#9-Redish的主从复制：" class="headerlink" title="9.Redish的主从复制："></a>9.Redish的主从复制：</h2><h3 id="1-概念："><a href="#1-概念：" class="headerlink" title="1.概念："></a>1.概念：</h3><ul>
<li><p>Redis主从复制，Master 节点写操作，Slave 节点读操作，Master 和 Slave分别代表了一个个不同的 Redis Server 实例</p>
</li>
<li><p>另外定期的数据备份操作也是单独选择一个 Slave 去完成，这样可以最大程度发挥 Redis 的性能，为的是保证数据的弱一致性和最终一致性</p>
</li>
<li><p>另外，Master 和 Slave 的数据不是一定要即时同步的，但是在一段时间后 Master 和 Slave 的数据是趋于同步的，这就是最终一致性</p>
</li>
<li><p><strong>Replication Id</strong>：简称replid，是数据集的标记</p>
<ul>
<li>id一致则说明是同一数据集。</li>
<li>每一个master都有唯一的replid，slave则会继承master节点的replid（master如何得知salve是第一次来连接）</li>
</ul>
</li>
<li><p><strong>offset</strong>：偏移量</p>
<ul>
<li>随着记录在repl_baklog中的数据增多而逐渐增大。</li>
<li>slave完成同步时也会记录当前同步的offset。</li>
<li>如果slave的offset小于master的offset，说明slave数据落后于master，需要更新。</li>
</ul>
</li>
<li><p>repl_baklog文件：</p>
<ul>
<li>这个文件是一个固定大小的数组，只不过数组是环形</li>
<li><strong>角标到达数组末尾后，会再次从0开始读写</strong>，这样数组头部的数据就会被覆盖。</li>
<li>repl_baklog大小有上限，写满后会覆盖最早的数据。如果slave断开时间过久，导致数据被覆盖，则无法实现增量同步，只能再次全量同步。</li>
</ul>
</li>
<li><p>全量同步：<strong>主从第一次建立连接时</strong>，会执行全量同步，将master节点的所有数据都拷贝给slave节点</p>
<ol>
<li>slave节点请求增量同步</li>
<li>master节点判断replid，发现不一致，拒绝增量同步</li>
<li>master将完整内存数据生成RDB，发送RDB到slave</li>
<li>slave<strong>清空本地数据</strong>，加载master的RDB</li>
<li>master将RDB期间的命令记录在repl_baklog，并持续将log中的命令发送给slave</li>
<li>slave执行接收到的命令，保持与master之间的同步</li>
</ol>
</li>
<li><p>增量同步：除了第一次做全量同步，其它大多数时候slave与master都是做<strong>增量同步</strong>。</p>
<ol>
<li>Master 接收到用户的操作指令，判断是否需要传播到 Slave。</li>
<li>将操作记录追加到 AOF 文件。</li>
<li>将操作传播到其他 Slave：对齐主从库；往响应缓存写入指令。</li>
<li>将缓存中的数据发送给 Slave。</li>
</ol>
</li>
</ul>
<h3 id="2-搭建主从："><a href="#2-搭建主从：" class="headerlink" title="2.搭建主从："></a>2.搭建主从：</h3><ul>
<li><p>复制redis的配置文件为redis-6380.conf</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cp /etc/redis.conf /root/rediscluster/redis-6380.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>修改文件内容：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">vim /root/rediscluster/redis-6380.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改内容</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改端口号</span></span><br><span class="line">port 6380</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">后台运行</span></span><br><span class="line">daemonize yes</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改pid文件名</span></span><br><span class="line">pidfile &quot;/var/run/redis_6379.pid&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改持久化文件名</span></span><br><span class="line">dbfilename &quot;dump_6379.rdb&quot;</span><br><span class="line">dir &quot;/rediscluster&quot;</span><br></pre></td></tr></table></figure>
</li>
<li><p>复制redis-6380.conf成两份文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cp redis-6380.conf redis-6381.conf</span><br><span class="line">cp redis-6380.conf redis-6382.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>通过sed修改内容：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sed -i &#x27;s/6380/6381/g&#x27; ./redis-6381.conf </span><br><span class="line">sed -i &#x27;s/6380/6382/g&#x27; ./redis-6382.conf </span><br></pre></td></tr></table></figure>
</li>
<li><p>启动服务：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">redis-server redis-6380.conf</span><br><span class="line">redis-server redis-6381.conf</span><br><span class="line">redis-server redis-6382.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看redis的进程：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps -ef | grep redis</span><br></pre></td></tr></table></figure>
</li>
<li><p>连接服务：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -p 6380</span><br><span class="line">redis-cli -p 6381</span><br><span class="line">redis-cli -p 6382</span><br></pre></td></tr></table></figure>
</li>
<li><p>选择两种方案中的一种进行配置，在5.0以后新增命令replicaof，与salveof效果一致。</p>
<ul>
<li><p>修改配置文件（永久生效）</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">方式一：vim</span></span><br><span class="line">replicaof 192.168.73.141 7001    -- 告诉redis1（Master）节点自己是slave</span><br></pre></td></tr></table></figure>

<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">方式二：sed</span></span><br><span class="line">sed -i &#x27;s/^# replicaof &lt;masterip&gt; &lt;masterport&gt;/replicaof 127.0.0.1 6380/&#x27; redis-6381.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用redis-cli客户端连接到redis服务，执行slaveof命令（重启后失效）：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">slaveof 192.168.73.141 7001     -- 告诉redis1（Master）节点自己是slave</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>查看从节点状态</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -p 6380 info replication</span><br><span class="line">redis-cli -p 6381 info replication</span><br><span class="line">redis-cli -p 6382 info replication</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="3-主从切换："><a href="#3-主从切换：" class="headerlink" title="3.主从切换："></a>3.主从切换：</h3><ul>
<li><p>当一个 master 宕机后，后面的 slave 可以立刻升为 master，其后面的 slave 不用做任何修改。</p>
</li>
<li><p>用 slaveof no one 将从机变为主机。</p>
</li>
<li><p>假设主机 6380 宕机了，我们可以在 6381 上执行如下命令来切换为主机：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis<span class="operator">-</span>cli <span class="operator">-</span>p <span class="number">6381</span> slaveof <span class="keyword">no</span> <span class="keyword">one</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>查看从节点状态</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis<span class="operator">-</span>cli <span class="operator">-</span>p <span class="number">6381</span> info replication</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="10-哨兵模式："><a href="#10-哨兵模式：" class="headerlink" title="10.哨兵模式："></a>10.哨兵模式：</h2><h3 id="1-概念：-1"><a href="#1-概念：-1" class="headerlink" title="1.概念："></a>1.概念：</h3><ul>
<li><p>哨兵也叫 sentinel，Redis提供了哨兵（Sentinel）机制来实现<strong>主从集群的自动故障恢复</strong>。</p>
</li>
<li><p>哨兵的作用如下：</p>
<ul>
<li><strong>监控</strong>：Sentinel 会不断检查您的master和slave是否按预期工作</li>
<li><strong>自动故障恢复</strong>：如果master故障，Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主</li>
<li><strong>通知</strong>：Sentinel充当Redis客户端的服务发现来源，当集群发生故障转移时，会将最新信息推送给Redis的客户端</li>
</ul>
</li>
<li><p>集群监控原理：</p>
<ul>
<li><p>Sentinel基于心跳机制监测服务状态，每隔1秒向集群的每个实例发送ping命令</p>
</li>
<li><p>主观下线：如果<strong>某sentinel节点</strong>发现某实例未在规定时间响应，则认为该实例<strong>主观下线</strong>。</p>
</li>
<li><p>客观下线：若<strong>超过指定数量（quorum）的sentinel</strong>都认为该实例主观下线，则该实例<strong>客观下线</strong>。quorum值最好超过Sentinel实例数量的一半。</p>
</li>
</ul>
</li>
<li><p>图示：</p>
<img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230220200926039.png" alt="image-20230220200926039" style="zoom:67%;" /></li>
</ul>
<h3 id="2-搭建哨兵集群："><a href="#2-搭建哨兵集群：" class="headerlink" title="2.搭建哨兵集群："></a>2.搭建哨兵集群：</h3><ul>
<li><p>在 &#x2F;root&#x2F;rediscluster 目录下新建 sentinel.conf 文件，文件名称不能写错，必须叫这个名称</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">vim sentinel.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改内容</span></span><br><span class="line">sentinel monitor redismaster 127.0.0.1 6379 1</span><br></pre></td></tr></table></figure>

<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">参数说明：</span></span><br><span class="line">monitor：监控</span><br><span class="line">redismaster：为监控对象起的服务名称</span><br><span class="line">1：为至少有多个个哨兵同意迁移的数量</span><br></pre></td></tr></table></figure>
</li>
<li><p>启动哨兵：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-sentinel sentinel.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>验证哨兵是否可用：关闭主redis服务</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -p 6380 shutdown</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看从节点状态</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -p 6381 info replication</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="3-复制延时："><a href="#3-复制延时：" class="headerlink" title="3.复制延时："></a>3.复制延时：</h3><ul>
<li>由于所有的写操作都是先在Master上操作，然后同步更新到Slave上，所以从Master同步到Slave机器有一定的延迟，当系统很繁忙的时候，延迟问题会更加严重，Slave机器数量的增加也会使这个问题更加严重。</li>
</ul>
<h3 id="4-选举策略："><a href="#4-选举策略：" class="headerlink" title="4.选举策略："></a>4.选举策略：</h3><ol>
<li>选择优先级靠前的服务器。优先级的配置在 redis.conf 文件中的 replica-priority 配置，默认为 100，值越小优先级越高。</li>
<li>选择偏移量最大的。偏移量是指获得原主机数据最全的。</li>
<li>选择 runid 最小的从服务器。每个redis实例启动后都会随机生成一个40位的runid</li>
</ol>
<h2 id="11-集群环境："><a href="#11-集群环境：" class="headerlink" title="11.集群环境："></a>11.集群环境：</h2><h3 id="1-集群的介绍："><a href="#1-集群的介绍：" class="headerlink" title="1.集群的介绍："></a>1.集群的介绍：</h3><ul>
<li>Redis 集群是一个提供在多个 Redis 间节点间共享数据的程序集。</li>
<li>Redis集群并不支持处理多个keys的命令，因为这需要在不同的节点间移动数据，从而达不到像Redis那样的性能，在高负载的情况下可能会导致不可预料的错误</li>
<li>Redis 集群通过分区来提供一定程度的可用性，在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。Redis 集群的优势:<ul>
<li>自动分割数据到不同的节点上。</li>
<li>整个集群的部分节点失败或者不可达的情况下能够继续处理命令。</li>
</ul>
</li>
</ul>
<h3 id="2-数据分片："><a href="#2-数据分片：" class="headerlink" title="2.数据分片："></a>2.数据分片：</h3><ul>
<li>Redis 集群没有使用一致性hash，而是引入了哈希槽（slots）的概念。</li>
<li>Redis 集群有16384个哈希槽，每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽，比如当前集群有3个节点，那么：<ul>
<li>节点 A 包含 0 到 5500号哈希槽。</li>
<li>节点 B 包含5501 到 11000 号哈希槽。</li>
<li>节点 C 包含11001 到 16384号哈希槽。</li>
</ul>
</li>
<li>这种结构很容易添加或者删除节点。比如想新添加个节点D，只需要从节点 A、B、C中得部分槽并分配到D上即可。</li>
<li>如果想移除节点A，需要将A中的槽移到B和C节点上，然后将没有任何槽的A节点从集群中移除即可。</li>
<li>由于从一个节点将哈希槽移动到另一个节点并不会停止服务，所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。</li>
</ul>
<h3 id="3-集群搭建："><a href="#3-集群搭建：" class="headerlink" title="3.集群搭建："></a>3.集群搭建：</h3><ul>
<li><p>开启两个主机，一台上开启3个redis服务：</p>
<table>
<thead>
<tr>
<th align="center">IP</th>
<th align="center">PORT</th>
<th align="center">角色</th>
</tr>
</thead>
<tbody><tr>
<td align="center">192.168.178.101</td>
<td align="center">7001</td>
<td align="center">master</td>
</tr>
<tr>
<td align="center">192.168.178.101</td>
<td align="center">7002</td>
<td align="center">master</td>
</tr>
<tr>
<td align="center">192.168.178.101</td>
<td align="center">7003</td>
<td align="center">master</td>
</tr>
<tr>
<td align="center">192.168.178.151</td>
<td align="center">8001</td>
<td align="center">slave</td>
</tr>
<tr>
<td align="center">192.168.178.151</td>
<td align="center">8002</td>
<td align="center">slave</td>
</tr>
<tr>
<td align="center">192.168.178.151</td>
<td align="center">8003</td>
<td align="center">slave</td>
</tr>
</tbody></table>
</li>
<li><p>把之前主从复制中所产生的所有持久文件先清除。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm -f dump*</span><br></pre></td></tr></table></figure>
</li>
<li><p>复制redis的配置文件到指定目录下</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir /root/cluster</span><br></pre></td></tr></table></figure>
</li>
<li><p>修改配置文件</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">vim redis-7001.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改内容</span></span><br><span class="line"></span><br><span class="line">include /root/cluster/redis.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改端口号</span></span><br><span class="line">port 7001</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改pid文件名</span></span><br><span class="line">pidfile &quot;/var/run/redis_7001.pid&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">持久化文件存放目录</span></span><br><span class="line">dir &quot;/cluster&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">修改持久化文件名</span></span><br><span class="line">dbfilename &quot;dump_7001.rdb&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">绑定地址</span></span><br><span class="line">bind 0.0.0.0</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">让redis后台运行</span></span><br><span class="line">daemonize yes</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">注册的实例ip</span></span><br><span class="line">replica-announce-ip 192.168.72.101</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">保护模式,如果开启了protected-mode，那么在没有设定<span class="built_in">bind</span> ip且没有设密码的情况下，Redis只允许接受本机的响应。</span></span><br><span class="line">protected-mode no</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">日志</span></span><br><span class="line">logfile /cluster/log/run-7001.log</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">开启集群功能</span></span><br><span class="line">cluster-enabled yes</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设定节点配置文件名，不需要我们创建，由redis自己维护</span></span><br><span class="line">cluster-config-file ./nodes-7001.conf</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">节点心跳失败的超时时间，超过该时间（毫秒），集群自动进行主从切换</span></span><br><span class="line">cluster-node-timeout 10000</span><br></pre></td></tr></table></figure>
</li>
<li><p>如果希望开启 aof 持久化功能，则还需添加如下配置：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">开启aof持久化</span></span><br><span class="line">appendonly yes</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置aof持久化文件名</span></span><br><span class="line">appendfilename aof-6380.aof</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">配置同步方式</span></span><br><span class="line">appendfsync everysec</span><br><span class="line">no-appendfsync-on-rewrite yes</span><br><span class="line">auto-aof-rewrite-percentage 100</span><br><span class="line">auto-aof-rewirte-min-size 64mb</span><br></pre></td></tr></table></figure>
</li>
<li><p>修改其他多个服务，通过以下命令</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sed &#x27;s/6379/6380/g&#x27; redis-7002.conf </span><br></pre></td></tr></table></figure>
</li>
<li><p>启动所有服务：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">redis-server redis-7001.conf</span><br><span class="line">redis-server redis-7002.conf</span><br><span class="line">redis-server redis-7003.conf</span><br><span class="line">redis-server redis-8001.conf</span><br><span class="line">redis-server redis-8002.conf</span><br><span class="line">redis-server redis-8003.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看 Redis 服务进程</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps -ef | grep redis</span><br></pre></td></tr></table></figure>
</li>
<li><p>创建集群：虽然服务启动了，但是目前每个服务之间都是独立的，没有任何关联。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>redis-cli –cluster</td>
<td>代表集群操作命令</td>
</tr>
<tr>
<td>create</td>
<td>代表是创建集群</td>
</tr>
<tr>
<td>–replicas 1<code>或者</code>–cluster-replicas 1</td>
<td>指定集群中每个master的从节点个数为1</td>
</tr>
</tbody></table>
</li>
<li><p>通过命令可以查看集群状态：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -c -p 7001 cluster nodes</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="4-测试集群："><a href="#4-测试集群：" class="headerlink" title="4.测试集群："></a>4.测试集群：</h3><ul>
<li><p>对集群操作时，需要给 redis-cli 加上 -c 参数</p>
</li>
<li><p>尝试连接 6379 节点（连接任何一个节点都可以），存储一个数据：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 连接</span><br><span class="line">redis-cli -h 192.168.72.101 -c -p 7001</span><br><span class="line"># 存储数据</span><br><span class="line">set num 123</span><br><span class="line"># 读取数据</span><br><span class="line">get num</span><br><span class="line"># 再次存储</span><br><span class="line">set a 1</span><br></pre></td></tr></table></figure>
</li>
<li><p>向集群批量添加值：</p>
<ul>
<li><p>在集群环境下，由于 redis-cli 每次录入、查询键值时，Redis 都会计算出该 key 对应的插槽值，并交给对应插槽所在的节点进行处理。如果不是该客户端对应服务器的插槽 Redis 会报错</p>
</li>
<li><p>当我们在集群下使用 mset 或 mget 来添加多个值或查询多个值时：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:7001&gt; mset name lisi age 20</span><br><span class="line">(error) CROSSSLOT keys in request don&#x27;t hash to the same slot</span><br></pre></td></tr></table></figure>
</li>
<li><p>解决方法：我们可以使用自定义组来完成，通过一对大括号 {} 来定义一个相同的组名，从而使 key 中的 {} 内相同内容的键值对放到同一个 slot 中</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:7002&gt; mset name&#123;user&#125; lisi age&#123;user&#125; 20</span><br><span class="line">-&gt; Redirected to slot [4867] located at 192.168.72.101:6379</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>向集群查询值：</p>
<ul>
<li><p>查看组开始的插槽值</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:7001&gt; cluster keyslot user</span><br><span class="line">(integer) 4867</span><br></pre></td></tr></table></figure>
</li>
<li><p>统计自己插槽所在范围的值（在自己创建的主从上查看）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:7001&gt; cluster countkeysinslot 4867 #只能统计自己插槽所在范围的值</span><br><span class="line">(integer) 2</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看具体键值：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:7001&gt; cluster getkeysinslot 4867 10</span><br><span class="line">1) &quot;name&#123;user&#125;&quot;</span><br><span class="line">2) &quot;age&#123;user&#125;&quot;</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<h3 id="5-故障转移："><a href="#5-故障转移：" class="headerlink" title="5.故障转移："></a>5.故障转移：</h3><ul>
<li><p>假设我们让 7001 所以服务器宕机</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -c -p 7001 shutdown</span><br></pre></td></tr></table></figure>
</li>
<li><p>然后执行 cluster nodes 命令查看集群状态：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -c -p 7002 cluster nodes</span><br></pre></td></tr></table></figure>
</li>
<li><p>这时发现，7005从slave节点变成master节点；7001节点上的数据保存到7002和从节点中</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[root@zhanglin slicecluster]# redis-cli -c -p 7002</span><br><span class="line">127.0.0.1:7002&gt; keys *</span><br><span class="line">1) &quot;age&#123;user&#125;&quot;</span><br><span class="line">2) &quot;set&#123;user&#125;&quot;</span><br><span class="line">3) &quot;name&quot;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="6-集群扩容："><a href="#6-集群扩容：" class="headerlink" title="6.集群扩容："></a>6.集群扩容：</h3><ul>
<li><p>我们向现有集群中添加两个节点，这两个节点做了一主一从。主节点的端口号为 7007，从节点的端口号为 7008。</p>
</li>
<li><p>创建配置文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mv ./redis-7001.conf ./redis-7007.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>启动服务:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">redis-server redis-7007.conf</span><br><span class="line">redis-server redis-7008.conf</span><br></pre></td></tr></table></figure>
</li>
<li><p>添加主节点：add-node命令用于添加节点到集群中</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id &lt;arg&gt;</span><br><span class="line">例：redis-cli --cluster add-node 192.168.178.101:7007 192.168.178.101:7001</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">参数：</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">new_host：被添加节点的主机地址</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">new_port：被添加节点的端口号</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">existing_host：目前集群中已经存在的任一主机地址</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">existing_port：目前集群中已经存在的任一端口地址</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-slave：用于添加从（Slave）节点</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-master-id：指定主（Master）节点的ID（唯一标识）字符串</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>添加从节点：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">先查看主节点的ID值</span></span><br><span class="line">redis-cli -c -p 7008 cluster nodes</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用主节点的ID值添加从节点到集群中</span> </span><br><span class="line">redis-cli --cluster add-node 192.168.72.101:6386 192.168.178.101:7008 --cluster-slave --cluster-master-id 1982a39401caaf04d283545f2b8cf292eb64f211</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看主节点和从节点是否添加成功：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -c -p 7008 cluster nodes</span><br></pre></td></tr></table></figure>
</li>
<li><p>分配插槽：将新主节点的插槽分配100个槽给新从节点</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">reshard host:port --cluster-from [分配主节点ID值] --cluster-to [被分配从节点ID值] --cluster-slots [num] --cluster-yes --cluster-timeout [num] --cluster-pipeline [num] --cluster-replace</span><br><span class="line">例：# redis-cli --cluster reshard 192.168.178.101:7007 --cluster-from [7007redis的ID值] --cluster-to</span><br><span class="line">[7008redis的ID值] --cluster-slots 100 --cluster-yes --cluster-timeout 5000 --cluster-pipeline 10 --cluster-replace</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">参数：</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">host：集群中已经存在的任意主机地址</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">port：集群中已经存在的任意主机对应的端口号</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-from：表示slot目前所在的节点node ID，多个ID用逗号分隔</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-to：表示需要分配节点的node ID</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-slot：分配的slot数量</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-yes：指定迁移时的确认输入</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-timeout：设置migrate命令的超时时间</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">cluster-pipeline：定义cluster getkeysinslot命令一次取出的key数量，不传的话使用默认值为10</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--cluster-replace：是否直接replace到目标节点</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>查看是否分槽成功：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -c -p 7008 cluster nodes</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="7-集群缩容"><a href="#7-集群缩容" class="headerlink" title="7.集群缩容:"></a>7.集群缩容:</h3><ul>
<li><p>删除从节点：</p>
<ul>
<li><p>收回分片：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">redis-cli --cluster reshard 192.168.178.101:7007 --cluster-from [7007redis的ID值] --cluster-to</span><br><span class="line">[7003redis的ID值] --cluster-slots 100 --cluster-yes --cluster-timeout 5000 --cluster-pipeline 10 --cluster-replace</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看集群状态：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; redis-cli -c -p 6379 cluster nodes</span><br></pre></td></tr></table></figure>
</li>
<li><p>删除从节点：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli --cluster del-node 192.168.178.101:7006 [要删除的节点ID值]</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看是否安装成功：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -c -p 7006 cluster nodes</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
<li><p>删除主节点：</p>
<ul>
<li><p>删除：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli --cluster del-node 192.168.178.101:7006 [要删除的节点ID值]</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看是否安装成功：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -c -p 7006 cluster nodes</span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<h3 id="8-集群的优缺点："><a href="#8-集群的优缺点：" class="headerlink" title="8.集群的优缺点："></a>8.集群的优缺点：</h3><ul>
<li>优点：<ul>
<li>扩容方便</li>
<li>分摊压力</li>
<li>无中心配置相对简单</li>
</ul>
</li>
<li>缺点：<ul>
<li>多键操作是不被支持的</li>
<li>多键的Redis事务是不被支持的。lua脚本不被支持</li>
</ul>
</li>
</ul>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">Author: </span><span class="post-copyright-info"><a href="http://example.com">阿尔托莉雅</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">Link: </span><span class="post-copyright-info"><a href="http://example.com/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/B2.NoSQL%E6%95%B0%E6%8D%AE%E5%BA%93%20-%20Redis/">http://example.com/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/B2.NoSQL%E6%95%B0%E6%8D%AE%E5%BA%93%20-%20Redis/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">Copyright Notice: </span><span class="post-copyright-info">All articles in this blog are licensed under <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> unless stating additionally.</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Redis-NoSQL-%E6%95%B0%E6%8D%AE%E5%BA%93/">Redis NoSQL 数据库</a></div><div class="post_share"><div class="social-share" data-image="/images/Otherwallpaper/avatar.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/B3.NoSQL%E6%95%B0%E6%8D%AE%E5%BA%93%20-%20MongDB/" title="NoSQL篇-MongDB数据库"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">Previous Post</div><div class="prev_info">NoSQL篇-MongDB数据库</div></div></a></div><div class="next-post pull-right"><a href="/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/A1.MySQL-%E6%AC%A7%E9%B9%8F%E7%AF%87/" title="SQL篇-MySQL数据库"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">Next Post</div><div class="next_info">SQL篇-MySQL数据库</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="/images/Otherwallpaper/avatar.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">阿尔托莉雅</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">Articles</div><div class="length-num">11</div></a><a href="/tags/"><div class="headline">Tags</div><div class="length-num">4</div></a><a href="/categories/"><div class="headline">Categories</div><div class="length-num">2</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://toscode.gitee.com/blue-fantasy" target="_blank" title="Gitee"><i class="fab fa-github"></i></a><a class="social-icon" href="/1095322098@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>Announcement</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>Catalog</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-NoSQL%E7%9A%84%E6%A6%82%E5%BF%B5%EF%BC%9A"><span class="toc-number">1.</span> <span class="toc-text">1.NoSQL的概念：</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-Redis%E6%A6%82%E5%BF%B5%EF%BC%9A"><span class="toc-number">2.</span> <span class="toc-text">2.Redis概念：</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%EF%BC%9A"><span class="toc-number">3.</span> <span class="toc-text">3.下载安装：</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-redis%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%EF%BC%9A"><span class="toc-number">4.</span> <span class="toc-text">4.redis的数据结构：</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-%E5%91%BD%E4%BB%A4%E6%93%8D%E4%BD%9C%EF%BC%9A"><span class="toc-number">5.</span> <span class="toc-text">5.命令操作：</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E9%80%9A%E7%94%A8%E5%91%BD%E4%BB%A4%EF%BC%9A"><span class="toc-number">5.1.</span> <span class="toc-text">2.通用命令：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-String%E7%B1%BB%E5%9E%8B%EF%BC%9A"><span class="toc-number">5.2.</span> <span class="toc-text">3.String类型：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-Hash%E7%B1%BB%E5%9E%8B%EF%BC%9A"><span class="toc-number">5.3.</span> <span class="toc-text">4.Hash类型：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-List%E7%B1%BB%E5%9E%8B%EF%BC%9A"><span class="toc-number">5.4.</span> <span class="toc-text">5.List类型：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-%E9%9B%86%E5%90%88%E7%B1%BB%E5%9E%8B-set%EF%BC%9A"><span class="toc-number">5.5.</span> <span class="toc-text">6.集合类型 set：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88%E7%B1%BB%E5%9E%8B-sortedset%EF%BC%9A"><span class="toc-number">5.6.</span> <span class="toc-text">7.有序集合类型 sortedset：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8-%E4%BD%8D%E6%93%8D%E4%BD%9CBitmaps%EF%BC%9A"><span class="toc-number">5.7.</span> <span class="toc-text">8.位操作Bitmaps：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#9-%E5%9F%BA%E6%95%B0%E7%BB%9F%E8%AE%A1HyperLog%EF%BC%9A"><span class="toc-number">5.8.</span> <span class="toc-text">9.基数统计HyperLog：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#10-%E7%BB%8F%E7%BA%AC%E5%BA%A6GEO%EF%BC%9A"><span class="toc-number">5.9.</span> <span class="toc-text">10.经纬度GEO：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-Redis%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-number">6.</span> <span class="toc-text">5.Redis的配置文件:</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-Units%EF%BC%9A"><span class="toc-number">6.1.</span> <span class="toc-text">1.Units：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-network%EF%BC%9A"><span class="toc-number">6.2.</span> <span class="toc-text">2.network：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-general%EF%BC%9A"><span class="toc-number">6.3.</span> <span class="toc-text">3.general：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-security%EF%BC%9A"><span class="toc-number">6.4.</span> <span class="toc-text">4.security：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-clients%EF%BC%9A"><span class="toc-number">6.5.</span> <span class="toc-text">5.clients：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-Redis%E5%8F%91%E5%B8%83%E4%B8%8E%E8%AE%A2%E9%98%85%EF%BC%9A"><span class="toc-number">7.</span> <span class="toc-text">6.Redis发布与订阅：</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7-%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%EF%BC%9A"><span class="toc-number">8.</span> <span class="toc-text">7.事务管理：</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E4%BA%8B%E5%8A%A1%E5%AE%9A%E4%B9%89%EF%BC%9A"><span class="toc-number">8.1.</span> <span class="toc-text">1.事务定义：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-Multi%E3%80%81Exec%E3%80%81discard%EF%BC%9A"><span class="toc-number">8.2.</span> <span class="toc-text">2.Multi、Exec、discard：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-%E4%BA%8B%E5%8A%A1%E7%9A%84%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86%EF%BC%9A"><span class="toc-number">8.3.</span> <span class="toc-text">3.事务的错误处理：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-%E4%BA%8B%E5%8A%A1%E7%9A%84%E5%86%B2%E7%AA%81%E9%97%AE%E9%A2%98%EF%BC%9A"><span class="toc-number">8.4.</span> <span class="toc-text">4.事务的冲突问题：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-%E6%95%B0%E6%8D%AE%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%9A"><span class="toc-number">9.</span> <span class="toc-text">8.数据持久化：</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E5%88%86%E7%B1%BB%EF%BC%9A"><span class="toc-number">9.1.</span> <span class="toc-text">1.分类：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-RDB%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%9A"><span class="toc-number">9.2.</span> <span class="toc-text">2.RDB持久化：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-AOF%E6%8C%81%E4%B9%85%E5%8C%96%EF%BC%9A"><span class="toc-number">9.3.</span> <span class="toc-text">3.AOF持久化：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-RDB%E4%B8%8EAOF%E7%9A%84%E5%AF%B9%E6%AF%94%EF%BC%9A"><span class="toc-number">9.4.</span> <span class="toc-text">4.RDB与AOF的对比：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9-Redish%E7%9A%84%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%EF%BC%9A"><span class="toc-number">10.</span> <span class="toc-text">9.Redish的主从复制：</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E6%A6%82%E5%BF%B5%EF%BC%9A"><span class="toc-number">10.1.</span> <span class="toc-text">1.概念：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E6%90%AD%E5%BB%BA%E4%B8%BB%E4%BB%8E%EF%BC%9A"><span class="toc-number">10.2.</span> <span class="toc-text">2.搭建主从：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-%E4%B8%BB%E4%BB%8E%E5%88%87%E6%8D%A2%EF%BC%9A"><span class="toc-number">10.3.</span> <span class="toc-text">3.主从切换：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10-%E5%93%A8%E5%85%B5%E6%A8%A1%E5%BC%8F%EF%BC%9A"><span class="toc-number">11.</span> <span class="toc-text">10.哨兵模式：</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E6%A6%82%E5%BF%B5%EF%BC%9A-1"><span class="toc-number">11.1.</span> <span class="toc-text">1.概念：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E6%90%AD%E5%BB%BA%E5%93%A8%E5%85%B5%E9%9B%86%E7%BE%A4%EF%BC%9A"><span class="toc-number">11.2.</span> <span class="toc-text">2.搭建哨兵集群：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-%E5%A4%8D%E5%88%B6%E5%BB%B6%E6%97%B6%EF%BC%9A"><span class="toc-number">11.3.</span> <span class="toc-text">3.复制延时：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-%E9%80%89%E4%B8%BE%E7%AD%96%E7%95%A5%EF%BC%9A"><span class="toc-number">11.4.</span> <span class="toc-text">4.选举策略：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#11-%E9%9B%86%E7%BE%A4%E7%8E%AF%E5%A2%83%EF%BC%9A"><span class="toc-number">12.</span> <span class="toc-text">11.集群环境：</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E9%9B%86%E7%BE%A4%E7%9A%84%E4%BB%8B%E7%BB%8D%EF%BC%9A"><span class="toc-number">12.1.</span> <span class="toc-text">1.集群的介绍：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E6%95%B0%E6%8D%AE%E5%88%86%E7%89%87%EF%BC%9A"><span class="toc-number">12.2.</span> <span class="toc-text">2.数据分片：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA%EF%BC%9A"><span class="toc-number">12.3.</span> <span class="toc-text">3.集群搭建：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-%E6%B5%8B%E8%AF%95%E9%9B%86%E7%BE%A4%EF%BC%9A"><span class="toc-number">12.4.</span> <span class="toc-text">4.测试集群：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-%E6%95%85%E9%9A%9C%E8%BD%AC%E7%A7%BB%EF%BC%9A"><span class="toc-number">12.5.</span> <span class="toc-text">5.故障转移：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-%E9%9B%86%E7%BE%A4%E6%89%A9%E5%AE%B9%EF%BC%9A"><span class="toc-number">12.6.</span> <span class="toc-text">6.集群扩容：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-%E9%9B%86%E7%BE%A4%E7%BC%A9%E5%AE%B9"><span class="toc-number">12.7.</span> <span class="toc-text">7.集群缩容:</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#8-%E9%9B%86%E7%BE%A4%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9%EF%BC%9A"><span class="toc-number">12.8.</span> <span class="toc-text">8.集群的优缺点：</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>Recent Post</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/B3.NoSQL%E6%95%B0%E6%8D%AE%E5%BA%93%20-%20MongDB/" title="NoSQL篇-MongDB数据库">NoSQL篇-MongDB数据库</a><time datetime="2023-03-13T12:32:38.445Z" title="Created 2023-03-13 20:32:38">2023-03-13</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/B2.NoSQL%E6%95%B0%E6%8D%AE%E5%BA%93%20-%20Redis/" title="NoSQL篇-Redis数据库">NoSQL篇-Redis数据库</a><time datetime="2023-03-13T12:32:38.441Z" title="Created 2023-03-13 20:32:38">2023-03-13</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/03/13/4.%E6%95%B0%E6%8D%AE%E5%BA%93/A1.MySQL-%E6%AC%A7%E9%B9%8F%E7%AF%87/" title="SQL篇-MySQL数据库">SQL篇-MySQL数据库</a><time datetime="2023-03-13T12:32:38.437Z" title="Created 2023-03-13 20:32:38">2023-03-13</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/03/13/3.linux/D2.Ansible%E5%89%A7%E6%9C%AC/" title="Ansible">Ansible</a><time datetime="2023-03-13T12:32:23.866Z" title="Created 2023-03-13 20:32:23">2023-03-13</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/03/13/3.linux/D1.Ansible%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E5%B7%A5%E5%85%B7/" title="Ansible基础">Ansible基础</a><time datetime="2023-03-13T12:32:23.861Z" title="Created 2023-03-13 20:32:23">2023-03-13</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By 阿尔托莉雅</div><div class="framework-info"><span>Framework </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>Theme </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="Read Mode"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="Toggle Between Light And Dark Mode"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="Toggle between single-column and double-column"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="Setting"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="Table Of Contents"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="Back To Top"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>